/*
 *
 *  *
 *  *      Copyright 2020-2021 Luter.me
 *  *
 *  *      Licensed under the Apache License, Version 2.0 (the "License");
 *  *      you may not use this file except in compliance with the License.
 *  *      You may obtain a copy of the License at
 *  *
 *  *        http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  *      Unless required by applicable law or agreed to in writing, software
 *  *      distributed under the License is distributed on an "AS IS" BASIS,
 *  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *      See the License for the specific language governing permissions and
 *  *      limitations under the License.
 *  *
 *
 */

package com.luter.heimdall.core.listener;


import com.luter.heimdall.core.exception.HeimdallException;
import com.luter.heimdall.core.token.SimpleToken;
import com.luter.heimdall.core.utils.StrUtils;
import org.slf4j.Logger;

import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Token Store 事件监听
 *
 * @author luter
 */
public abstract class AbstractTokenStoreEvent implements TokenEventListener {
    /**
     * The constant log.
     */
    private static final transient Logger log = getLogger(AbstractTokenStoreEvent.class);
    /**
     * The Listeners.
     */
    private Collection<TokenEventListener> listeners = new CopyOnWriteArrayList<>();

    @Override
    public String name() {
        return "";
    }

    @Override
    public void onCreated(SimpleToken token) {
        log.debug("[onTokenCreated]::token = [{}]", token);
        for (TokenEventListener listener : this.listeners) {
            try {
                listener.onCreated(token);
                log.warn("[onTokenCreated:({})]:: token = [{}]", listener.name(), token);
            } catch (Exception e) {
                log.error("[onTokenCreated:({})]::Listening processing error. token = [{}],exception= {}", listener.name(), token, e);
            }
        }
    }

    @Override
    public void onRead(SimpleToken token) {
        log.debug("[onTokenRead]::token = [{}]", token);
        for (TokenEventListener listener : this.listeners) {
            try {
                listener.onRead(token);
                log.debug("[onTokenRead:({})]:: token = [{}]", listener.name(), token);
            } catch (Exception e) {
                log.error("[onTokenCreated:({})]::Listening processing error. token = [{}],exception= {}", listener.name(), token, e);
            }
        }
    }

    @Override
    public void onUpdated(SimpleToken token) {
        log.debug("[onTokenUpdated]::token = [{}]", token);
        for (TokenEventListener listener : this.listeners) {
            try {
                listener.onUpdated(token);
                log.debug("[onTokenUpdated:({})]:: token = [{}]", listener.name(), token);
            } catch (Exception e) {
                log.error("[onTokenUpdated:({})]::Listening processing error. token = [{}],exception= {}", listener.name(), token, e);
            }
        }
    }

    @Override
    public void onDeleted(SimpleToken token) {
        log.debug("[onTokenDeleted]::token = [{}]", token);
        for (TokenEventListener listener : this.listeners) {
            try {
                listener.onDeleted(token);
                log.debug("[onTokenDeleted:({})]::  token = [{}]", listener.name(), token);
            } catch (Exception e) {
                log.error("[onTokenDeleted:({})]::Listening processing error. token = [{}],exception= {}", listener.name(), token, e);
            }
        }
    }

    public void addListener(TokenEventListener eventListener) {
        final boolean present = listeners.stream().anyMatch(listener -> listener.name().equals(eventListener.name()));
        if (present) {
            throw new HeimdallException("A TokenEventListener named [ " + eventListener.name() + " ]  already exists ." +
                    "  Failed to add TokenEventListener. Please set a different name and try again.");
        }
        log.info("[addListener]:: new  eventListener added,name  = [{}]", eventListener.name());
        this.getListeners().add(eventListener);
    }

    public void deleteListener(String name) {
        if (StrUtils.isNotBlank(name)) {
            final boolean b = listeners.removeIf(listener -> listener.name().equals(name));
            log.info("[deleteListener]:: delete Listener, name = [{}], result = [{}]", name, b);
        } else {
            log.warn("[deleteListener]:: The listener is null, ignored.  name = [{}]", name);
        }

    }

    public int getSize() {
        return this.getListeners().size();
    }

    /**
     * Gets listeners.
     *
     * @return the listeners
     */
    @Override
    public Collection<TokenEventListener> getListeners() {
        return listeners;
    }

    /**
     * Sets listeners.
     *
     * @param listeners the listeners
     */
    public void setListeners(Collection<TokenEventListener> listeners) {
        this.listeners = listeners;
    }

}
